<?php

/**
 * Created by IntelliJ IDEA.
 * User: zhoumengkang
 * Date: 15/9/24
 * Time: 上午1:19
 */
class DbConnection
{

    private static $_instance = array();	//Instance of this singleton

    private $dsn = '';
    private $user = '';
    private $pass = '';

    private $dbh = null;
    private $stmt = null;

    /**
     * 静态工厂方法，返还此类的唯一实例
     */
    public static function getInstance($dsn, $user, $pass)
    {
        $key = md5($dsn);

        if(self::$_instance == null){
            self::$_instance = array();
        }

        if (array_key_exists($key,self::$_instance) && self::$_instance[$key] == true) {}else{
            self::$_instance[$key] = new self($dsn, $user, $pass);
        }

        return self::$_instance[$key];
    }

    private function __construct($dsn, $user, $pass)
    {
        $this->dsn = $dsn;
        $this->user = $user;
        $this->pass = $pass;
    }

    public function __destruct()
    {
        $this->stmt = null;
        $this->dbh = null;
    }

    private function init()
    {
        if($this->dbh) return true;
        $this->dbh = new PDO($this->dsn, $this->user, $this->pass, array(
                PDO::ATTR_PERSISTENT => false,                  //是否使用长连接
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,    //抛出PDOException异常
                PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
                PDO::ATTR_TIMEOUT => 10,
            )
        );
    }

    public function prepare($sql)
    {
        $this->init();
        $this->stmt = $this->dbh->prepare($sql);
        if(!$this->stmt)
            throw new Exception("Error SQL:$sql");
        return $this->stmt;
    }

    public function bind($param,$var)
    {
        $this->stmt->bindParam($param,$var);
    }

    public function execute($sql=null,$binds=null)
    {
        $this->prepare($sql);

        if(is_array($binds)){
            foreach($binds as $k=>$v){
                $this->bind($k+1,$v);
            }
        }

        return $this->stmt->execute();
    }

    public function query($sql,$binds=null)
    {
        $ok = $this->execute($sql,$binds);
        $this->stmt->closeCursor();
        return $ok;
    }

    public function next($style=PDO::FETCH_ASSOC)
    {
        return $row = $this->stmt->fetch($style);
    }

    public function getValue($sql,$binds=null)
    {
        $this->execute($sql,$binds);
        $value = $this->stmt->fetch(PDO::FETCH_COLUMN);
        $this->stmt->closeCursor();
        return $value;
    }

    public function getOne($sql,$binds=null,$style=PDO::FETCH_ASSOC)
    {
        $this->execute($sql,$binds);
        $row = $this->stmt->fetch($style);
        $this->stmt->closeCursor();
        return $row;
    }

    public function getAll($sql,$binds=null,$style=PDO::FETCH_ASSOC)
    {
        $this->execute($sql,$binds);
        $rows = $this->stmt->fetchAll($style);
        $this->stmt->closeCursor();
        return $rows;
    }

    public function getColumn($sql,$binds=null)
    {
        $this->execute($sql,$binds);
        return $this->stmt->fetchAll(PDO::FETCH_COLUMN);
    }

    public function getInsertId()
    {
        return $this->dbh->lastInsertId();
    }

    public function closeCursor()
    {
        if($this->stmt)
            $this->stmt->closeCursor();
        $this->stmt = null;
    }

    public function close()
    {
        $this->closeCursor();
        $this->dbh = null;
        self::$_instance = null;
    }
}